package com.csx.governance.traffic.core.config;

import com.csx.governance.traffic.core.RequestAfterCompletionCleaner;
import com.csx.governance.traffic.core.TrafficGovernanceRuleLocator;
import com.csx.governance.traffic.core.TrafficGovernanceRuleRefreshListener;
import com.csx.governance.traffic.core.TrafficMessageParameterExtractor;
import com.csx.governance.traffic.core.interceptor.TrafficHandlerInterceptorRunner;
import com.csx.governance.traffic.core.interceptor.inbound.RequestAfterCompletionInboundHandlerInterceptor;
import com.csx.governance.traffic.core.interceptor.inbound.TrafficAbstractInboundHandlerInterceptor;
import com.csx.governance.traffic.core.interceptor.inbound.TransportAttributesPutInboundHandlerInterceptor;
import com.csx.governance.traffic.core.interceptor.outbound.RequestAttributesInitializerOutboundHandlerInterceptor;
import com.csx.governance.traffic.core.interceptor.outbound.TrafficAbstractOutboundHandlerInterceptor;
import com.csx.governance.traffic.core.interceptor.outbound.TransportAttributesTakeOutboundHandlerInterceptor;
import com.csx.governance.traffic.core.metadata.EnvironmentServiceMetadataProvider;
import com.csx.governance.traffic.core.metadata.ServiceMetadataLocator;
import com.csx.governance.traffic.core.metadata.ServiceMetadataProvider;
import com.csx.governance.traffic.core.support.DefaultRequestAfterCompletionCleaner;
import com.csx.governance.traffic.core.support.HttpReactiveRequestHeaderExtractor;
import com.csx.governance.traffic.core.support.HttpServletRequestHeaderExtractor;
import com.csx.governance.traffic.core.support.TrafficMessageParameterExtractorRunner;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

import java.util.List;

/**
 * @author cuisongxu
 * @date 2023/3/5 16:27
 */
@EnableConfigurationProperties(TrafficGovernanceServiceProperties.class)
@Configuration
@ConditionalOnProperty(value = "traffic.governance.enabled", havingValue = "true", matchIfMissing = true)
public class TrafficGovernanceCoreAutoConfiguration {

    @Bean
    public TrafficGovernanceRuleRefreshListener trafficGovernanceRuleRefreshListener(List<TrafficGovernanceRuleLocator<?>> trafficGovernanceRuleLocators) {
        return new TrafficGovernanceRuleRefreshListener(trafficGovernanceRuleLocators);
    }

    @Bean
    public ServiceMetadataLocator trafficServiceMetadataLocator(List<ServiceMetadataProvider> providers) {
        return new ServiceMetadataLocator(providers);
    }

    @Bean
    public ServiceMetadataProvider environmentServiceMetadataProvider(Environment environment) {
        return new EnvironmentServiceMetadataProvider(environment);
    }

    @Bean
    public RequestAfterCompletionCleaner defaultRequestAfterCompletionCleaner() {
        return new DefaultRequestAfterCompletionCleaner();
    }

    @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
    @Bean
    public TrafficMessageParameterExtractor httpServletRequestHeaderExtractor() {
        return new HttpServletRequestHeaderExtractor();
    }

    @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
    @Bean
    public TrafficMessageParameterExtractor httpReactiveRequestHeaderExtractor() {
        return new HttpReactiveRequestHeaderExtractor();
    }

    @Bean
    public TrafficMessageParameterExtractorRunner trafficMessageParameterExtractorRunner(List<TrafficMessageParameterExtractor> trafficMessageParameterExtractors) {
        return new TrafficMessageParameterExtractorRunner(trafficMessageParameterExtractors);
    }

    // ****************************************** 拦截器 -inbound ******************************************
    // TODO 考虑可以通过配置的方式关闭拦截器
    @Bean(name = "inboundHandlerInterceptorRunner")
    public TrafficHandlerInterceptorRunner inboundHandlerInterceptorRunner(List<TrafficAbstractInboundHandlerInterceptor> trafficAbstractInboundHandlerInterceptors) {
        return new TrafficHandlerInterceptorRunner(trafficAbstractInboundHandlerInterceptors);
    }

    @Bean
    public TrafficAbstractInboundHandlerInterceptor requestAfterCompletionInboundHandlerInterceptor(List<RequestAfterCompletionCleaner> requestAfterCompletionCleaners) {
        return new RequestAfterCompletionInboundHandlerInterceptor(requestAfterCompletionCleaners);
    }

    @Bean
    public TrafficAbstractInboundHandlerInterceptor transportAttributesPutInboundHandlerInterceptor() {
        return new TransportAttributesPutInboundHandlerInterceptor();
    }

    // ****************************************** 拦截器 -outbound ******************************************

    @Bean(name = "outboundHandlerInterceptorRunner")
    public TrafficHandlerInterceptorRunner outboundHandlerInterceptorRunner(List<TrafficAbstractOutboundHandlerInterceptor> trafficAbstractOutboundHandlerInterceptors) {
        return new TrafficHandlerInterceptorRunner(trafficAbstractOutboundHandlerInterceptors);
    }

    @Bean
    public TrafficAbstractOutboundHandlerInterceptor transportAttributesTakeOutboundHandlerInterceptor() {
        return new TransportAttributesTakeOutboundHandlerInterceptor();
    }

    @Bean
    public TrafficAbstractOutboundHandlerInterceptor requestAttributesInitializerOutboundHandlerInterceptor() {
        return new RequestAttributesInitializerOutboundHandlerInterceptor();
    }

}
